/*
 * File:   Donjons.cpp
 * Author: poitevjo
 *
 * Created on 24 novembre 2011, 15:57
 */

#include "Donjons.h"



//Constructeur de la classe//
Donjons::Donjons(int longueurx,int longueury) {
    this->longueurx = longueurx;
    this->longueury = longueury;
    int i,j;
    for (i=0;i<longueury;i++){
        for (j=0;j<longueurx;j++){
            Cases.push_back(Case(i,j));

        }

    }
    this->Clear();
}


int Donjons::getLargeur(){
    return longueurx;
}

int Donjons::getHauteur(){
    return longueury;
}

Case Donjons::getCase(int i, int j) {
    c = Cases[i*getLargeur()+j];
    return c;
}


///////////////////////////Methodes d'affichage/////////////////////////////////

//Affiche le donjons avec tous ses elements//
void Donjons::Afficher(){
    int i,j;
        cout << "Voici le Donjons : " << endl;
        cout << "Longueur sur les x : " << longueurx << endl;
        cout << "Longueur sur les y : " << longueury << endl;


                for(i=0;i<=longueury-1;i++){

                        for(j=0;j<=longueurx-1;j++){
                        cout << Cases[i*longueurx+j].getsymbole();
                        }
                        cout << endl;
                }
}

//////////////////////////Methodes d'ajout d'element////////////////////////////

//Ajout Salle//
void Donjons::AjouterSalle(Salle S){
    if ((S.getCasegen().getx() > 0)
      &&(S.getCasegen().gety() > 0)
      &&((S.getCasegen().getx() + S.getlongueurx() - 1)<= longueurx)
      &&((S.getCasegen().gety() + S.getlongueury() - 1)<= longueury)){
        //La salle peut etre inserer dans le donjons

                Salles.push_back(S);

    }
}

//Ajout Couloir//
void Donjons::AjouterCouloir(Couloir C){

                Couloirs.push_back(C);

}


///////////////////////////////Methodes de generation///////////////////////////

//Generation du donjons a partir des element existant//
void Donjons::Generer(){
    this->Clear();
    vector<Case> Cs;
    char sym1,sym2;
    int i,j;
    //Integration des salles une a une en gerant les colisions
    for(i=0;i<Salles.size();i++){
        Cs = Salles[i].getCases();
        for(j=0;j<Cs.size();j++){

            sym1 = Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].getsymbole(); //Case présente sur la carte
            sym2 = Cs[j].getsymbole(); //Case a prendre en compte

            if( sym1 == SymVide || sym2 == SymVide){
                    //la case est libre
                    Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole('.');
            }
            else if((sym1 == SymMurHor || sym1 == SymCroi || sym1==SymMurVer)
                  &&(sym2 == SymMurHor || sym2 == SymCroi || sym2 ==SymMurVer)){
                  //Croisement de mur
                if(sym1!= sym2){
                    //Mur identique dons pas de croisement
                    Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole(SymCroi);
                }


            }
            else {
                    //On ecrase la case deja presente(meme s'il s'agit d'un mur)
                    Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole(sym2);
            }
        }
    }
    //Integration des couloir un a un en gerant la sortie des salles(porte)
    //et sans "ecraser" les paroi des salles

    //une paroi:                +
    //                          |
    //      +--------+    ou    |
    //                          |
    //                          +

    bool porte=false;
    for(i=0;i<Couloirs.size();i++){
        Cs = Couloirs[i].getCases();
        for(j=0;j<Cs.size();j++){
            sym1 = Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].getsymbole(); //Case présente sur la carte
            sym2 = Cs[j].getsymbole(); //Case a prendre en compte

            //mise en place des couloirs sans "ecraser" les murs
            if(porte == false){
                if(sym1 == SymFond ||sym1 == SymMurHor ||sym1 == SymMurVer ||sym1 == SymCroi){
                 Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole(sym2);
                 //On ecrase la case deja presente s'il s'agit d'un mur ou du fond
                }
                if(sym1 == SymMurHor || sym1 == SymMurVer ){
                porte = true;
                //On a ecrase un mur donc on a crer une porte
                }
            }else if(sym1 == SymMurHor || sym1 == SymMurVer){
                //dans le cas ou on a ecraser un mur il faut faire attention
                //que l'on ne va pas ecraser une paroi d'une Salle
                 if(j+1<=Cases.size()){
                     if(Cases[ (Cs[j+1].gety()*longueurx)+Cs[j+1].getx()].getsymbole() != SymMurHor
                      &&Cases[ (Cs[j+1].gety()*longueurx)+Cs[j+1].getx()].getsymbole() != SymMurVer){
                         Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole(sym2);
                         //On a verifier que la case prochaine n'est pas un mur donc on
                         //n'est pas en train d'ecraser une paroi mais de creer une porte
                         //entre deux paroi consecutive
                         porte = false;
                     }
                 }
            }else{
                //Le symbole courant sur le donjons n'est pas un mur donc on peut reprendre
                //la construction du couloir en sachant que l'on n'ecrase pas une paroi
                porte = false;
                if(sym1 == SymFond ||sym1 == SymMurHor ||sym1 == SymMurVer ||sym1 == SymCroi){
                 Cases[ (Cs[j].gety()*longueurx)+Cs[j].getx()].setsymbole(sym2);
                }
            }
        }
        porte = false;
    }
        cout << "Donjons généré" << endl;
}



//Generation d'un nombre de salle choisi par l'utilisateur//
//===>le nombre sera en parametre//
void Donjons::GenerationAleatoire(int nb){
    int i;
    int longx,longy,x,y;
    int p = Salles.size();//A partir d'ou on ajoute des salle dans le vecteur
                          //(on peut en creer manuelement avant d'en generer aléatoirement)
    Case c;
    Salle s;
    Couloir co;
    srand(time(NULL));

    //Création aleatoire des salles en etant dans les norme du donjons
    for(i=0;i<nb;i++){
        longx = (rand() % (longXmax-longXmin))+longXmin;
        longy = (rand() % (longYmax-longYmin))+longYmin;
        x = (rand() %(this->longueurx -longx));
        y = (rand() %(this->longueury - longy));
        c = Case(x,y);
        s = Salle(c,longx,longy);
        this->AjouterSalle(s);
    }
    //Creation des couloirs pour relier les salles créer précédement
    for(i=p;i<Salles.size()-1;i++){
        co = Couloir(Salles[i],Salles[i+1]);
        this->AjouterCouloir(co);
    }
    //On relie l'ensemble aux salles précédement créer
    if(p!=0){
        co = Couloir(Salles[p],Salles[p-1]);
        this->AjouterCouloir(co);
    }
    this->Generer();
    this->Afficher();
    cout << "Génération aleatoire terminée" << endl;

}


//Nettoyage de toute les cases composant le donjons//
void Donjons::Clear(){
    int i;
    for(i=0;i<Cases.size();i++){
        Cases[i].setsymbole(SymFond);
    }
}
